#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>

#define MAXLINE     1024
#define COPROCESS   "./add"

void sig_pipe(int sig)
{
    printf("caught SIGPIPE\n");
    exit(0);
}

int main(int argc, char *argv[])
{
    int n, fd1[2], fd2[2];
    pid_t pid;
    char line[MAXLINE];

    signal(SIGPIPE, sig_pipe);

    if (pipe(fd1) < 0 || pipe(fd2) < 0)
    {
        perror("pipe error");
        exit(0);
    }

    if ((pid = fork()) > 0)
    {
        close(fd1[0]);
        close(fd2[1]);

        while (fgets(line, MAXLINE, stdin) != NULL)
        {
            n = strlen(line);
            if (write(fd1[1], line, n) != n)
            {
                perror("write error");
                exit(0);
            }
            
            if ((n = read(fd2[0], line, MAXLINE)) < 0)
            {
                perror("read error");
                exit(0);
            }

            line[n] = 0;
            if (fputs(line, stdout) == EOF)
            {
                perror("fputs error");
                exit(0);
            }
        }
    
        if (ferror(stdin))
        {
            perror("fgets error");
            exit(0);
        }
    }
    else
    {
        close(fd1[1]);
        close(fd2[0]);

        if (fd1[0] != STDIN_FILENO)
        {
            if (dup2(fd1[0], STDIN_FILENO) < 0)
            {
                perror("dup2 STDIN_FILENO error");
                exit(0);
            }

            close(fd1[0]);
        }

        if (fd2[1] != STDOUT_FILENO)
        {
            if (dup2(fd2[1], STDOUT_FILENO) < 0)
            {
                perror("dup2 STDOUT_FILENO error");
                exit(0);
            }

            close(fd2[1]);
        }

        if (execl(COPROCESS, COPROCESS, NULL) < 0)
        {
            perror("execl error");
            exit(0);
        }
    }

    return 0;
}
